home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-06-22 | 9.5 KB | 437 lines | [TEXT/CWIE] |
- // Better Unmount
- //
- // (C) 1996 Damon Cokenias All Rights Reserved
- // cokenias@mtn-palace.com
- //
- #ifndef __powerc /* (uses fake universal proc ptrs!) */
-
- #include <A4Stuff.h>
-
- #define kErrorAlertID 6010
- #define kErrorAlert2ID 6013
- #define kConfirmAlertID 6012
-
- #define kProcResType 'Proc'
- #define kProcResID 128
-
- #define kSettingsResType 'PREF'
- #define kSettingsResID 128
-
- #define kFirstStrID 128
-
- #define kDisplayItemsButton 3
-
- #define kMaxVolumesToRemember 60
-
- typedef pascal void (*InitMenusProc) (void);
- typedef pascal short (*AlertProc) (short alertID, ModalFilterUPP filterProc);
-
- typedef pascal void (*DoDisplayItemsProc) (short vRefNum);
-
- typedef struct {
- short silentUnmount;
- } SettingsRec, **SettingsHandle;
-
- UniversalProcPtr gUnmountProc = NULL;
- InitMenusProc gInitMenusProc = NULL;
- AlertProc gAlertProc = NULL;
- Boolean gPatchesInstalled = false;
- Boolean gTriggered = false;
- SettingsRec gSettings;
- AliasHandle gMeAlias = NULL;
- short gVRefNums [kMaxVolumesToRemember];
- short gNumVRefNums = 0;
-
- asm void MyUnmountVol (void);
- pascal void MyInitMenus (void);
- pascal short MyAlert (short alertID, ModalFilterUPP filterProc);
- Boolean IsErrorMessage ();
- Boolean IsConfirmMessage ();
- Boolean StartsWith (const unsigned char* s, const unsigned char* prefix);
- Boolean EndsWith (const unsigned char* s, const unsigned char* suffix);
- AliasHandle MakeAliasToSelf ();
- short DoErrorAlert (ModalFilterUPP filterProc, short whichAlert);
- void DoDisplayItems (short vRefNum);
- pascal Boolean MyFilterProc (DialogPtr dlog, EventRecord* event, short* itemHit);
- void SimulateClick (DialogPtr dlog, short item);
-
- void DoDisplayItems (short vRefNum)
- {
- DoDisplayItemsProc* proc;
-
- proc = (DoDisplayItemsProc*) Get1Resource (kProcResType, kProcResID);
- if (!proc) {
- SysBeep (1);
- return;
- } else {
- HLockHi ((Handle) proc);
- (*proc) (vRefNum);
- ReleaseResource ((Handle) proc);
- }
- }
-
- enum {
- kErrorPrefixStr,
- kErrorPrefixStr2,
- kErrorSuffixStr,
- kConfirmPrefixStr,
- kConfirmSuffixStr,
- kNumStrings
- };
-
- StringHandle gStrings [kNumStrings];
-
- void SimulateClick (DialogPtr dlog, short item)
- {
- Rect bounds;
- short itemType;
- Handle itemHandle;
- long ticks;
-
- GetDialogItem (dlog, kDisplayItemsButton, &itemType, &itemHandle, &bounds);
- HiliteControl ((ControlHandle) itemHandle, 1);
- Delay (8, &ticks);
- HiliteControl ((ControlHandle) itemHandle, 0);
- }
-
- pascal Boolean MyFilterProc (DialogPtr dlog, EventRecord* event, short* itemHit)
- {
- Boolean retVal = false;
-
- EnterCodeResource ();
-
- if (event -> what == keyDown || event -> what == autoKey) {
-
- if (event -> modifiers & cmdKey) {
-
- switch (event -> message & charCodeMask) {
- case 'd' :
- *itemHit = kDisplayItemsButton;
- SimulateClick (dlog, kDisplayItemsButton);
- retVal = true;
- break;
- }
- }
- }
-
- Exit:
-
- ExitCodeResource ();
- return retVal;
- }
-
- short DoErrorAlert (ModalFilterUPP filterProc, short whichAlert)
- {
- short oldResFile = CurResFile ();
- short itemHit;
- FSSpec mySpec;
- short myResFile;
- OSErr error;
- Boolean wasChanged;
- Boolean gotResources = false;
-
- /* find my resources */
- error = ResolveAlias (nil, gMeAlias, &mySpec, &wasChanged);
- if (error == noErr) {
- myResFile = FSpOpenResFile (&mySpec, fsRdPerm);
- if (myResFile > 0)
- gotResources = true;
- }
-
- if (gotResources) {
- short vRefNum, i;
-
- // itemHit = Alert (whichAlert, MyFilterProc); not done w/ filter proc
- itemHit = Alert (whichAlert, nil);
-
- if (gNumVRefNums) {
- vRefNum = gVRefNums [0];
- for (i = 1; i < gNumVRefNums; ++i)
- gVRefNums [i - 1] = gVRefNums [i];
- --gNumVRefNums;
-
- if (itemHit == kDisplayItemsButton) {
- DoDisplayItems (vRefNum);
- itemHit = 1;
- } else if (itemHit == 1) {
- gNumVRefNums = 0;
- }
- }
- } else
- itemHit = Alert (whichAlert, filterProc);
-
-
- Exit:
- if (gotResources) {
- CloseResFile (myResFile);
- UseResFile (oldResFile);
- }
-
- return itemHit;
- }
-
- AliasHandle MakeAliasToSelf ()
- {
- short myRefNum = CurResFile ();
- FCBPBRec pb;
- FSSpec mySpec;
- OSErr error;
- AliasHandle a;
- AliasHandle sysHandle;
- long length;
-
- pb.ioFCBIndx = 0;
- pb.ioNamePtr = mySpec.name;
- pb.ioRefNum = myRefNum;
-
- if (PBGetFCBInfoSync (&pb))
- return nil;
-
- mySpec.vRefNum = pb.ioFCBVRefNum;
- mySpec.parID = pb.ioFCBParID;
-
- error = NewAlias (nil, &mySpec, &a);
- if (error)
- return nil;
-
- length = GetHandleSize ((Handle) a);
- sysHandle = (AliasHandle) NewHandleSys (length);
- if (!sysHandle) {
- DisposeHandle ((Handle) a);
- return nil;
- }
-
- BlockMoveData (*a, *sysHandle, length);
- DisposeHandle ((Handle) a);
-
- return sysHandle;
- }
-
- Boolean StartsWith (const unsigned char* s, const unsigned char* prefix)
- {
- int i;
-
- if (s[0] < prefix [0])
- return false;
-
- for (i = 1; i <= prefix [0]; ++i)
- if (s [i] != prefix [i])
- return false;
-
- return true;
- }
-
- Boolean EndsWith (const unsigned char* s, const unsigned char* suffix)
- {
- int i, offset;
-
- offset = s [0] - suffix [0];
-
- if (offset < 0)
- return false;
-
- for (i = 1; i <= suffix [0]; ++i)
- if (s [i + offset] != suffix [i])
- return false;
-
- return true;
- }
-
- Boolean IsErrorMessage ()
- {
- StringHandle s = LMGetDAStrings (0);
-
- if (s == nil)
- return false;
-
- return ((StartsWith (*s, *gStrings [kErrorPrefixStr]) ||
- StartsWith (*s, *gStrings [kErrorPrefixStr2])) &&
- EndsWith (*s, *gStrings [kErrorSuffixStr]));
- }
-
- Boolean IsConfirmMessage ()
- {
- StringHandle s = LMGetDAStrings (0);
-
- if (s == nil)
- return false;
-
- return (StartsWith (*s, *gStrings [kConfirmPrefixStr]) && EndsWith (*s, *gStrings [kConfirmSuffixStr]));
- }
-
-
- pascal short MyAlert (short alertID, ModalFilterUPP filterProc)
- {
- short itemHit;
-
- EnterCodeResource ();
-
- if (gSettings.silentUnmount && alertID == kConfirmAlertID && IsConfirmMessage ())
- itemHit = 1;
- else if (gTriggered == true && (alertID == kErrorAlertID || alertID == kErrorAlert2ID) &&
- IsErrorMessage ()) {
- gTriggered = false;
- itemHit = DoErrorAlert (filterProc, alertID);
- } else
- itemHit = (gAlertProc) (alertID, filterProc);
-
- ExitCodeResource ();
- return itemHit;
- }
-
- pascal void MyInitMenus (void)
- {
- long result;
- ProcessSerialNumber curPSN;
- ProcessInfoRec info;
-
- EnterCodeResource ();
-
- if (gPatchesInstalled)
- goto Exit;
-
- /* is there a process manager ? */
- if (Gestalt (gestaltOSAttr, &result))
- goto Exit;
-
- if ((result & gestaltLaunchControl) == 0)
- goto Exit;
-
- /* is this the Finder ? */
-
- curPSN.highLongOfPSN = 0;
- curPSN.lowLongOfPSN = kCurrentProcess;
-
- info.processInfoLength = sizeof (ProcessInfoRec);
- info.processName = nil;
- info.processAppSpec = nil;
- GetProcessInformation (&curPSN, &info);
-
- if (info.processSignature != 'MACS')
- goto Exit;
-
- // Install here
- gUnmountProc = GetOSTrapAddress (_UnmountVol);
- SetOSTrapAddress ((UniversalProcPtr) MyUnmountVol, _UnmountVol);
-
- gAlertProc = (AlertProc) GetToolTrapAddress (_Alert);
- SetToolTrapAddress ((UniversalProcPtr) MyAlert, _Alert);
-
- gPatchesInstalled = true;
-
- Exit:
-
- (gInitMenusProc) ();
-
- ExitCodeResource ();
- return;
- }
-
-
- /* called after a PBUnmountVol fails with fBsyErr */
- static
- void myTailPatch (ParmBlkPtr unmountPB)
- {
- EnterCodeResource ();
-
- if (unmountPB -> volumeParam.ioNamePtr) /* we're not interested if volume reference by name */
- goto Exit;
-
- if (gNumVRefNums == kMaxVolumesToRemember)
- goto Exit;
-
- gVRefNums [gNumVRefNums++] = unmountPB -> volumeParam.ioVRefNum;
-
- gTriggered = true;
-
- Exit:
- ExitCodeResource ();
- }
-
- asm void MyUnmountVol (void)
- {
- /*
- ** On entry, D1 contains the trap word used to call this routine
- ** A0 contains a ParmBlkPtr
- */
-
- BTST #0x09, D1 /* asynch version? */
- BNE exitToROM /* Yes, we don't deal with asynch calls */
-
- MOVE.L A0, -(SP) /* remember param block ptr */
- PEA tailPatch /* push addr of our tail patch */
-
- exitToROM:
-
- SUBQ.L #4, SP /* reserve spot on stack */
- MOVEM.L D0-D2/A0-A2/A4, -(SP) /* store regs */
- LEA SetCurrentA4, A0 /* setup A4 world */
- JSR (A0)
- MOVE.L gUnmountProc, 0x1C(sp) /* put global in previously reserved space */
- MOVEM.L (SP)+, D0-D2/A0-A2/A4 /* restore regs (including A4) */
- RTS /* will jump to rom address and return to 'tailPatch' */
-
- tailPatch: /* we get here when rom RTSs */
-
- MOVE.L (SP)+, A0 /* recall param block ptr */
- CMP.W #fBsyErr, D0 /* are there files open? */
- BEQ filesStillOpen /* yes, deal with it */
-
- returnToCaller:
- RTS /* return to original caller */
-
- filesStillOpen:
- MOVEM.L D0-D2/A0-A2, -(SP) /* store regs */
- MOVE.L A0, -(SP) /* push parameter */
- LEA myTailPatch, A0 /* call C routine */
- JSR (A0)
- ADDQ.L #4, SP /* pop parameter */
- MOVEM.L (SP)+, D0-D2/A0-A2 /* restore regs */
- BRA returnToCaller /* done */
- }
-
-
- void main ()
- {
- Boolean success = false;
- Handle self = Get1IndResource ('INIT', 1);
- SettingsHandle settings;
- short str;
-
- EnterCodeResource ();
-
- if (!self)
- goto Exit;
-
- settings = (SettingsHandle) Get1Resource (kSettingsResType, kSettingsResID);
- if (!settings)
- goto Exit;
-
- gSettings = **settings;
-
- for (str = 0; str < kNumStrings; ++str) {
- gStrings [str] = (StringHandle) Get1Resource ('STR ', kFirstStrID + str);
- if (!gStrings [str])
- goto Exit;
- }
-
- gMeAlias = MakeAliasToSelf ();
- if (!gMeAlias)
- goto Exit;
-
- /* detach all important resources */
-
- DetachResource (self);
- for (str = 0; str < kNumStrings; ++str)
- DetachResource ((Handle) gStrings [str]);
-
-
- gInitMenusProc = (InitMenusProc) GetToolTrapAddress (_InitMenus);
- SetToolTrapAddress ((UniversalProcPtr) MyInitMenus, _InitMenus);
-
- Exit:
-
- ExitCodeResource ();
- }
-
- #endif